package io.renren.common.aspect;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import io.renren.common.constant.Constant;
import io.renren.common.properties.RenrenProperties;
import io.renren.common.redis.RedisUtils;
import io.renren.common.utils.Result;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 防止重复提交切面
 *
 * @author txb
 */
@Slf4j
@Aspect
@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RepeatSubmitAspect {

    /**
     * 是否开启redis缓存  true开启   false关闭
     */
    private final RenrenProperties renrenProperties;
    private final RedisUtils redisUtils;
    private final static long DURATION = 3;

    /**
     * Local Cache  3秒过期
     */
    Cache<String, String> localCache = CacheUtil.newLRUCache(1000, 1000 * 3);

    @Around("execution(public * *(..))  && @annotation(io.renren.common.annotation.RepeatSubmit)")
    public Object interceptor(ProceedingJoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        String token = request.getHeader(Constant.TOKEN_HEADER);
        String key = token + "-" + request.getServletPath();
        if (StrUtil.isNotBlank(key)) {
            if (renrenProperties.getRedis().getOpen()) {
                if (ObjUtil.isNotEmpty(redisUtils.get(key))) {
                    return new Result<>().error("请勿重复请求！");
                }
                redisUtils.set(key, key, DURATION);
            } else {
                if (localCache.containsKey(key)) {
                    return new Result<>().error("请勿重复请求！");
                }
                localCache.put(key, key);
            }
        }
        return joinPoint.proceed();
    }
}
